import 'dart:convert' as JSON;
import 'dart:io';
import 'dart:math';

import 'package:dio/dio.dart';
import 'package:mziot/app/config/constant.dart';
import 'package:mziot/app/data/public_model.dart';
import 'package:mziot/app/tools/global_const.dart';
import 'package:mziot/app/tools/tools.dart';

import 'device.dart';

class Server {
  static String get domain {
    final env = GlobalConst.sharedPreferences?.getBool(Constant.env) ?? true;
    if (env) {
      return 'https://api.lgledsolutions.com/';
    } else {
      return 'https://third.chl6zk.store/';
    }
  }

  static String get web {
    final env = GlobalConst.sharedPreferences?.getBool(Constant.env) ?? true;
    if (env) {
      return 'https://file.lgledsolutions.com/';
    } else {
      return 'https://file.lgledsolutions.com/';
    }
  }
}

class ContentType {
  static String formData = "multipart/form-data";
  static String json = "application/json";
  static String formValue = "application/x-www-form-urlencoded";
  static String text = "application/text";
}

class LogInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    Map<String, dynamic> headers = {};
    final reqId = 10000000000 + Random().nextInt(1000000000);
    headers['reqId'] = reqId;
    headers['appVersion'] = DeviceUtils.version;
    headers['osType'] = DeviceUtils.osType;
    headers['osVersion'] = DeviceUtils.sysVersion;
    headers['deviceType'] = DeviceUtils.deviceName;
    headers['deviceId'] = DeviceUtils.deviceId;
    headers['netType'] = DeviceUtils.netType ?? "wifi";
    headers['wifiName'] = DeviceUtils.wifiName ?? "123";
    headers['wifiName'] = Uri.encodeComponent(headers['wifiName']);
    headers['timestamp'] = DateTime.now().millisecondsSinceEpoch ~/ 1000;
    if (GlobalConst.userModel?.token != null) {
      headers['token'] = GlobalConst.userModel!.token!;
    }
    if (GlobalConst.sharedPreferences?.getString(Constant.timeZone) != null) {
      headers['timezone'] = GlobalConst.sharedPreferences?.getString(Constant.timeZone);
    }
    int language = GlobalConst.sharedPreferences?.getInt(Constant.kLanguage) ?? 999;
    headers['language'] = 'English';
    if (language != 999) {
      if (language == 3) {
        headers['language'] = 'German';
      } else if (language == 2) {
        headers['language'] = 'French';
      } else if (language == 1) {
        headers['language'] = 'Chinese';
      }
    }

    String info = JSON.jsonEncode(headers);
    options.headers.addAll({'systemData': info});

    logger.v('request: ${options.uri} headers :${options.headers} data:${options.data}');
    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    logger.v(
        'respose: ${response.requestOptions.uri} ${response.requestOptions.data.toString()} ${response.toString()}');
    super.onResponse(response, handler);
  }

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) {
    logger.v('error ${err.requestOptions.uri} ${err.message} ${err.response.toString()}');
    super.onError(err, handler);
  }
}

class PublicProvider {
  factory PublicProvider() => _getInstance() ?? PublicProvider();

  static PublicProvider? get instance => _getInstance();

  // 静态变量_instance，存储唯一对象
  static PublicProvider? _instance;
  final Dio _dio = Dio();
  Dio get onlyDio => _dio;

  // 获取对象
  static PublicProvider? _getInstance() {
    _instance ??= PublicProvider._internal();

    return _instance;
  }

  PublicProvider._internal() {
    _dio.interceptors.add(LogInterceptor());
  }

  static _config() {
    instance!._dio.options.baseUrl = Server.domain;
    instance!._dio.options.method = 'POST';
    instance!._dio.options.contentType = ContentType.json;
    instance!._dio.options.connectTimeout = 10;
    instance!._dio.options.sendTimeout = 10;
    instance!._dio.options.receiveTimeout = 10;
    instance!._dio.options.responseType = ResponseType.json;
  }

  static Future<BaseModel<T>> request<T>({
    required String path,
    dynamic params,
    String? type,
    bool isAll = false,
  }) async {
    _config();
    var url = !isAll ? instance!._dio.options.baseUrl + path : path;
    if (Platform.isAndroid) {
      url = url.replaceAll('/ios', '/android');
    }
    final response = await instance?._dio
        .fetch(RequestOptions(path: url, method: 'POST', data: params, contentType: type));
    return BaseModel.fromJson(response);
  }

  static Future<dynamic> oriRequest({
    required String path,
    dynamic params,
    String? type,
  }) async {
    _config();
    final response = await instance?._dio
        .fetch(RequestOptions(path: path, method: 'POST', data: params, contentType: type));
    return response?.data;
  }
}
